package cn.itsource.service.impl;

import cn.hutool.core.util.ClassUtil;
import cn.itsource.annotation.Logs;
import cn.itsource.annotation.PreAuthorize;
import cn.itsource.domain.Article;
import cn.itsource.domain.ArticleType;
import cn.itsource.domain.Permission;
import cn.itsource.mapper.ArticleMapper;
import cn.itsource.mapper.ArticleTypeMapper;
import cn.itsource.mapper.PermissionMapper;
import cn.itsource.query.ArticleQuery;
import cn.itsource.service.IArticleService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.io.File;
import java.io.FileFilter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
public class ArticleServiceImpl implements IArticleService {
    @Autowired
    private ArticleMapper articleMapper;
    @Autowired
    private ArticleTypeMapper articleTypeMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private MongoTemplate mongoTemplate;
    @Logs
    @Transactional
    @Override
    @CacheEvict(cacheNames = "article", key = "'typeTree'")
    public void add(Article article) {
        articleMapper.add(article);
        mongoTemplate.save(article);
    }
    @Logs
    @Transactional
    @Override
    @CacheEvict(cacheNames = "article", key = "'typeTree'")
    public void update(Article article) {
        article.setUpdateTime(new Date());
        articleMapper.update(article);

        Query query = new Query(Criteria.where("id").is(article.getId()));
        Article mongoTemplateOne = mongoTemplate.findOne(query, Article.class);
        if (mongoTemplateOne != null){
            article.set_id(mongoTemplateOne.get_id());
        }
        mongoTemplate.save(article);
    }
    @Logs
    @Transactional
    @Override
    @CacheEvict(cacheNames = "article", key = "'typeTree'")
    public void del(Long id) {
        articleMapper.del(id);
        Query query = new Query(Criteria.where("id").is(id));
        mongoTemplate.remove(query, Article.class);
    }
    @Logs
    @Transactional
    @Override
    @CacheEvict(cacheNames = "article", key = "'typeTree'")
    public void delList(List<Long> ids) {
        articleMapper.delList(ids);
    }

    @Override
    public Article get(Long id) {
        return articleMapper.get(id);
    }

    @Override
    @Cacheable(cacheNames = "articleType", key = "'typeTree'")
    public List<ArticleType> getAll() {
        //将所有对象数据从数据库中 存入list中
        List<ArticleType> allTypes = articleTypeMapper.getAll();
        //充当缓存
        Map<Long,ArticleType> map = new HashMap<>();
        for (ArticleType allType : allTypes) {
            map.put(allType.getId(),allType);
        }
//        //list转为Map集合
//        Map<Long,ArticleType> map = allTypes.stream().collect(Collectors.toMap(ArticleType::getId,articleType->articleType));

        //空集合存储（一级）父级的类型
        ArrayList<ArticleType> oneLevelTypes = new ArrayList<>();
        for (ArticleType allType : allTypes) {
            //如果ParentId为空那么就是一级类型
            if (allType.getParentId() == null){
                //向集合添加一级类型
                oneLevelTypes.add(allType);
            }else { //只要是走else 那么就是二级三级四级.....
                //获取父级id
                Long parentId = allType.getParentId();
                //根据父级id拿到父级对象
                ArticleType parentArticleType = map.get(parentId);
                if (parentArticleType != null){
                    parentArticleType.getChildren().add(allType);
                }
            }
        }
        return oneLevelTypes;
    }
    @Override

    public PageInfo<Article> pageQuery(ArticleQuery query) {
        PageHelper.startPage(query.getCurrentPage(),query.getPageSize());
        List<Article> articles = articleMapper.pageQuery(query);
        redisTemplate.delete("typeTree");
        return new PageInfo<>(articles);
    }
    @Override
    public List<Article> getCorrelationArticles(Long id) {
        return articleMapper.getCorrelationArticles(id);
    }

    @Override
    public List<Article> getarticleTypes(Long id) {
        return articleMapper.getarticleTypes(id);
    }

}

